package com.sooth.micro.camunda.converter.processing.gateway;

import com.sooth.micro.camunda.converter.bean.BaseDefinition;
import com.sooth.micro.camunda.converter.bean.gateway.BranchNode;
import com.sooth.micro.camunda.converter.bean.gateway.ParallelGatewayDefinition;
import org.apache.commons.lang3.StringUtils;
import org.camunda.bpm.model.bpmn.builder.AbstractFlowNodeBuilder;
import org.camunda.bpm.model.bpmn.builder.ParallelGatewayBuilder;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class ParallelGatewayProcessor
        extends AbstractGatewayProcessor<ParallelGatewayDefinition, AbstractFlowNodeBuilder> {

    @Override
    public String onComplete(
            AbstractFlowNodeBuilder flowNodeBuilder, ParallelGatewayDefinition flowNode)
            throws InvocationTargetException, IllegalAccessException {
        String name = flowNode.getNodeName();
        ParallelGatewayBuilder parallelGatewayBuilder = flowNodeBuilder.parallelGateway().name(name);

        // create execution listener
        createExecutionListener(parallelGatewayBuilder, flowNode);
        List<BranchNode> branchNodes = flowNode.getBranchNodes();
        if (CollectionUtils.isEmpty(branchNodes) && Objects.isNull(flowNode.getNextNode())) {
            return parallelGatewayBuilder.getElement().getId();
        }

        List<String> incoming = new ArrayList<>(branchNodes.size());
        for (BranchNode branchNode : branchNodes) {
            BaseDefinition childNode = branchNode.getNextNode();
            if (Objects.isNull(childNode)) {
                incoming.add(parallelGatewayBuilder.getElement().getId());
                continue;
            }
            String id =
                    onCreate(
                            moveToNode(parallelGatewayBuilder, parallelGatewayBuilder.getElement().getId()),
                            childNode);
            if (StringUtils.isNotBlank(id)) {
                incoming.add(id);
            }
        }

        String id = parallelGatewayBuilder.getElement().getId();
        BaseDefinition nextNode = flowNode.getNextNode();
        if (Objects.nonNull(nextNode)) {
            nextNode.setIncoming(incoming);
            return merge(parallelGatewayBuilder, id, Collections.emptyList(), nextNode);
        }
        return id;
    }
}
